package com.zhilei.controller;

import com.google.gson.Gson;
import com.zhilei.base.BaseInfoProperties;
import com.zhilei.grace.result.GraceJSONResult;
import com.zhilei.grace.result.ResponseStatusEnum;
import com.zhilei.pojo.Users;
import com.zhilei.pojo.vo.SaasUserVO;
import com.zhilei.service.UsersService;
import com.zhilei.untils.JWTUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.UUID;

/**
 * 接收前端请求的数据的请求体，使用 @RequestBody 这会将请求的正文，就是请求的JSON转换为Java对象
 * 返回给前端数据，也就是将数据写入到JSON中发送给前端，使用 @ResponseBody
 *
 * @author zhilei
 * @data 2024-09-04
 */
@RestController
@RequestMapping("saas")
@Slf4j
public class SaasPassportController extends BaseInfoProperties {

    @Autowired
    private JWTUtils jwtUtils;

    @Autowired
    private UsersService usersService;

    /**
     * 获取二维码QRToken
     *
     * @return
     */
    @PostMapping("getQRToken")
    public GraceJSONResult getQRToken() {

        // TODO 1.使用UUID生成QRToken
        String qrToken = UUID.randomUUID().toString();

        // TODO 2.存入 redis中，并且设置过期时间5分钟
        redis.set(SAAS_PLATFORM_LOGIN_TOKEN + ":" + qrToken, qrToken, 5 * 60);

        // TODO 3.设置页面的刷新状态为0,设置过期时间是5分钟
        redis.set(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken, "0", 5 * 60);

        // TODO 4.返回QRToken，让前端请求的时候携带这个token过来
        return GraceJSONResult.ok(qrToken);
    }


    /**
     * 根据qrToken生成preToken，并且更改状态字段为1，标记为已扫码
     *
     * @param qrToken
     * @return
     */
    @PostMapping("scanCode")
    public GraceJSONResult scanCode(@RequestParam("qrToken") String qrToken, HttpServletRequest request) {

        // TODO 1.校验是否存在qrToken
        if (StringUtils.isBlank(qrToken)) {
            return GraceJSONResult.exception(ResponseStatusEnum.FAILED);
        }

        //  TODO 2.在redis中校验qrToken是否存在
        String saasQrToken = redis.get(SAAS_PLATFORM_LOGIN_TOKEN + ":" + qrToken);
        if (StringUtils.isBlank(saasQrToken)) {
            return GraceJSONResult.exception(ResponseStatusEnum.FAILED);
        }

        //  TODO 3.通过请求头获取请求的userId以及jwtToken
        String userId = request.getHeader("appUserId");
        String userJson = request.getHeader("appUserToken");

        // TODO 4.解析并截取jwtToken
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(userJson)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 5.校验userId和jwtToken是否存在
        String jwtToken = jwtUtils.checkJWT(userJson.split("@")[1]);
        log.error("jwt token: {}", jwtToken);
        if (StringUtils.isBlank(jwtToken)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 6.使用UUID生成随机的字符串
        String preToken = UUID.randomUUID().toString();

        // TODO 7.扫码之后覆盖掉之前的二维码信息
        redis.set(SAAS_PLATFORM_LOGIN_TOKEN + ":" + qrToken, preToken, 5 * 60);

        // TODO 8.修改二维码的数据状态为1
        redis.set(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken, "1," + preToken, 5 * 60);

        // TODO 9.返回QRToken，让前端请求的时候携带这个token过来
        return GraceJSONResult.ok(preToken);
    }


    /**
     * 扫描之后，后台页面弹出扫描成功的提示语
     *
     * @param qrToken
     * @return
     */
    @PostMapping("codeHasBeenRead")
    public GraceJSONResult codeHasBeenRead(@RequestParam("qrToken") String qrToken) {

        // TODO 1.校验是否存在qrToken
        if (StringUtils.isBlank(qrToken)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 2.在redis中校验qrToken是否存在
        String tokenStr = redis.get(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken);
        if (StringUtils.isBlank(tokenStr)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        ArrayList<Object> list = new ArrayList<>();

        // TODO 3.按照，分割字符串
        String[] tokens = tokenStr.split(",");
        if (tokens.length >= 2) {
            // 转换成数字类型
            Integer token = Integer.valueOf(tokens[0]);
            log.error("Invalid token； {}", token);

            list.add(token);
            list.add(tokens[1]);
            return GraceJSONResult.ok(list);
        } else {
            list.add(0);
            return GraceJSONResult.ok();
        }
    }

    /**
     * 手机端确认登录
     *
     * @param userId
     * @param qrToken
     * @param preToken
     * @return
     */
    @PostMapping("goQRLogin")
    public GraceJSONResult goQRLogin(@RequestParam("userId") String userId,
                                     @RequestParam("qrToken") String qrToken,
                                     @RequestParam("preToken") String preToken) {

        // TODO 1.校验传入的参数是否为空
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(qrToken) || StringUtils.isBlank(preToken)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 2.在redis中校验qrToken是否存在
        String tokenStr = redis.get(SAAS_PLATFORM_LOGIN_TOKEN_READ + ":" + qrToken);
        if (StringUtils.isBlank(tokenStr)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        String[] split = tokenStr.split(",");
        if (split.length < 2) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 3. 校验preToken是否与redis中的preToken匹配
        String redisPreToken = split[1];
        log.error("redisPreToken: {}", redisPreToken);
        if (!redisPreToken.equalsIgnoreCase(preToken)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 4. 校验userId是否与redis中的userId匹配
        Users users = usersService.getById(userId);
        if (users == null) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 5. 将users数据信息放到redis中
        redis.set(REDIS_SAAS_USER_INFO + ":temp:" + preToken, new Gson().toJson(users), 5 * 60);

        return GraceJSONResult.ok();
    }

    /**
     * 后端返回给前端jwtToken
     *
     * @param preToken
     * @return
     */
    @PostMapping("checkLogin")
    public GraceJSONResult checkLogin(@RequestParam("preToken") String preToken) {

        // TODO 1.校验传入的参数是否为空
        if (StringUtils.isBlank(preToken)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        // TODO 2.在redis中校验preToken是否存在
        String userStr = redis.get(REDIS_SAAS_USER_INFO + ":temp:" + preToken);
        if (StringUtils.isBlank(userStr)) {
            return GraceJSONResult.exception(ResponseStatusEnum.USER_STATUS_ERROR);
        }

        // TODO 3. 生成一个jwtToken，将token返回给前端
        String jwtToken = jwtUtils.createJWT(userStr, TOKEN_SAAS_PREFIX);

        redis.set(REDIS_SAAS_USER_INFO + ":" + jwtToken, userStr);

        return GraceJSONResult.ok(jwtToken);
    }

    /**
     * 根据redis的缓存获取用户数据
     *
     * @param token
     * @return
     */
    @GetMapping("info")
    public GraceJSONResult info(@RequestParam("token") String token) {

        // TODO 1.校验传入的参数是否为空
        if (StringUtils.isBlank(token)) {
            return GraceJSONResult.exception(ResponseStatusEnum.HR_TICKET_INVALID);
        }

        String jwtToken = token;

        // TODO 2.在redis中获取用户的数据
        String userJson = redis.get(REDIS_SAAS_USER_INFO + ":" + jwtToken);
        if (StringUtils.isBlank(userJson)) {
            return GraceJSONResult.exception(ResponseStatusEnum.USER_STATUS_ERROR);
        }

        // TODO 3. 转换成Users类型并返回
        Users users = new Gson().fromJson(userJson, Users.class);
        log.debug("info users: {}", users);
        SaasUserVO saasUserVO = new SaasUserVO();
        BeanUtils.copyProperties(users, saasUserVO);
        
        return GraceJSONResult.ok(saasUserVO);
    }

    /**
     * 退出登录
     *
     * @param token
     * @return
     */
    @PostMapping("logout")
    public GraceJSONResult logout(String token) {
        // TODO 1. 删除redis中存放的token
        String jwtToken = token;
        log.error("token: {}", token);
        redis.del(REDIS_SAAS_USER_INFO + ":" + jwtToken);
        // redis.del(REDIS_USER_TOKEN + ":" + userId);
        return GraceJSONResult.ok();
    }
}






















